<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 浅拷贝：只考虑对象类型
        function shallowCopy(obj) {
            if (typeof obj !== 'object') return;
            let newObj = obj instanceof Array ? [] : {}
            for (let key in ob) {
                if (obj.hasOwnProperty(key)) {
                    newObj[key] = obj[key]
                }
            }
            return newObj
        }

        // 简单版深拷贝：只考虑普通对象属性，不考虑内置对象和函数
        function deepClone(obj) {
            if (typeof obj !== 'object') return;
            var newObj = obj instanceof Array ? [] : {};
            for (var key in obj) {
                if (obj.hasOwnProperty(key)) {
                    newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
                }
            }
            console.log(newObj); // {name:'小明',age:18}
            return newObj
        }
        var obj = {
            name: '小明',
            age: 18
        }
        deepClone(obj)
        obj.name = '小花'
        console.log(obj); // {name:'小花',age:18}


        //复杂版深克隆：基于简单版的基础上，还考虑了内置对象比如 Date、RegExp 等对象和函数以及解决了循环引用的问题
        const isObject = (target) => (typeof target === 'object')

        function deepClone(target, map = new WeakMap()) {
            if (map.get(target)) {
                return target
            }
            // 获取当前值的构造函数：获取它的类型
            let constructor = target.constructor
                // 检测当前对象target是否与正则、日期格式对象匹配
            if (/^(RegExp|Date)$/i.test(constructor.name)) {
                // 创建一个新的特殊的对象（正则类、日期类）的实例
                return new constructor(target)
            }
            if (isObject(target)) {
                map.set(target, true) //为循环引用的对象做标记
                const cloneTarget = Array.isArray(target) ? [] : {}
                for (let prop in target) {
                    if (target.hasOwnProperty(prop)) {
                        cloneTarget[prop] = deepClone(target[prop], map)
                    }
                }
                return cloneTarget
            } else {
                return target
            }
        }
    </script>
</body>

</html>